package com.wzdigit.wms.raw.service.core;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.wms.basic.domain.asn.AsnDtl;
import com.wzdigit.wms.basic.domain.asn.AsnDtlGoods;
import com.wzdigit.wms.basic.domain.asn.AsnHeader;
import com.wzdigit.wms.basic.domain.dtos.inventory.UpdateInventoryInputDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.inventory.InvTrans;
import com.wzdigit.wms.basic.domain.inventory.Lotno;
import com.wzdigit.wms.basic.domain.order.TrsnDtl;
import com.wzdigit.wms.basic.domain.order.TrsnDtlGoods;
import com.wzdigit.wms.basic.domain.order.TrsnHeader;
import com.wzdigit.wms.basic.domain.qms.QmsIqc;
import com.wzdigit.wms.basic.enums.InvTransStatusEnum;
import com.wzdigit.wms.basic.enums.OpCodeEnum;
import com.wzdigit.wms.basic.enums.QaStatusEnum;
import com.wzdigit.wms.basic.enums.QmsOqcStatusEnum;
import com.wzdigit.wms.basic.enums.TrsnDtlGoodsStatusEnum;
import com.wzdigit.wms.basic.enums.TrsnDtlStatusEnum;
import com.wzdigit.wms.basic.enums.TrsnHeaderStatusEnum;
import com.wzdigit.wms.basic.enums.TrsnNoteTypeEnum;
import com.wzdigit.wms.basic.mapper.core.order.AsnDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.order.AsnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.order.AsnHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.order.TrsnHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.qms.QmsIqcMapper;
import com.wzdigit.wms.basic.service.code.InventoryService;
import com.wzdigit.wms.basic.service.code.LotnoService;
import com.wzdigit.wms.basic.util.common.SeparatorString;
import com.wzdigit.wms.raw.service.backtosap.CheckInStoreService;
import com.wzdigit.wms.raw.service.wmscommon.core.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName OqcInspApiImplService
 * @Description oqc判检接口实现类
 * @Author LHR-PC
 * @Date 2021/1/24 22:39
 * @Version
 **/
@Service
@Slf4j
public class OqcAsnService {
	
    @Autowired
    private AsnHeaderMapper asnHeaderMapper;

    @Autowired
    private AsnDtlMapper asnDtlMapper;

    @Autowired
    private AsnDtlGoodsMapper  asnDtlGoodsMapper;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private QmsIqcMapper qmsIqcMapper ;

    @Autowired
    private GoodsService goodsService;
    
    @Autowired
	private LotnoService lotnoService;
    
    @Autowired
    private TrsnHeaderMapper trsnHeaderMapper;
    
    @Autowired
    private TrsnDtlMapper trsnDtlMapper;
    
    @Autowired
    private TrsnDtlGoodsMapper trsnDtlGoodsMapper;
    
    @Autowired
    private CheckInStoreService checkInStoreService;
    
    @Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false)
    private BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;
    
    private static final String NOTE_NO = "TRSN_ORDER";
    
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void deal(String oqcNo, String userName, Integer qaStatus,String remark) throws Exception {
        //检验单
		log.info("调用raw判检接口");
        QueryWrapper<QmsIqc> qmsIqcQueryWrapper = new QueryWrapper<QmsIqc>();
        qmsIqcQueryWrapper.eq("OQC", oqcNo);
        QmsIqc qmsIqc = qmsIqcMapper.selectOne(qmsIqcQueryWrapper);
        
        // 送货单主档
        QueryWrapper<AsnHeader> asnHeaderQueryWrapper = new QueryWrapper<AsnHeader>();
        asnHeaderQueryWrapper.eq("ASN_NO", qmsIqc.getDeliveryNo());
        AsnHeader asnHeader = asnHeaderMapper.selectOne(asnHeaderQueryWrapper);
        
        // 送货单明细
        QueryWrapper<AsnDtl> asnDtlQueryWrapper = new QueryWrapper<AsnDtl>();
        asnDtlQueryWrapper.eq("ASN_HEADER_ID", asnHeader.getAsnHeaderId());
        asnDtlQueryWrapper.eq("INSP_NO", qmsIqc.getOqc());
        List<AsnDtl> asnDtlList = asnDtlMapper.selectList(asnDtlQueryWrapper);
        
        // 品质状态【旧、新】
        Integer oldQaStatus = asnDtlList.get(0).getQaStatus();
        Integer newQaStatus = Objects.equals(qaStatus, QmsOqcStatusEnum.JUDGE_RESULT_SUCCESS.getCode()) ? QaStatusEnum.OK.code : QaStatusEnum.NG.code;
        
        // 系统时间
        Date date = new Date();
        // 处理过的goodsSn
        Set<String> goodsSnSet = new HashSet<>();
        
        // 循环处理送货单明细---------------------------start---------------------//
        for (AsnDtl asnDtl : asnDtlList) {
        	// 当前送货单明细条码
         	QueryWrapper<AsnDtlGoods> asnDtlGoodsQueryWrapper = new QueryWrapper<AsnDtlGoods>();
         	asnDtlGoodsQueryWrapper.eq("ASN_DTL_ID", asnDtl.getAsnDtlId());
            List<AsnDtlGoods> asnDtlGoodsList = asnDtlGoodsMapper.selectList(asnDtlGoodsQueryWrapper);
            
            // 条码SN
            List<String> dtlSnList = asnDtlGoodsList.stream().map(AsnDtlGoods::getGoodsSn).distinct().collect(Collectors.toList());
            List<Goods> dtlGoodsList = goodsService.selectBySnList(dtlSnList);
            
            // 新增库存凭证--主档和明细
            BigDecimal trsnQty = asnDtlGoodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
	        TrsnDtl trsnDtl1 = insertTrsnHeaderAndTrsnDtl(oldQaStatus, trsnQty, asnDtl, asnHeader, -1, userName, date);
	        TrsnDtl trsnDtl2 = insertTrsnHeaderAndTrsnDtl(newQaStatus, trsnQty, asnDtl, asnHeader, 1, userName, date);
            
            // 根据【仓库、库位、货主、物料、组织、供应商、批次号、库存性质】分组统计
         	Map<String, List<Goods>> goodsMap = dtlGoodsList.stream().collect(Collectors.groupingBy(t ->
         		(t.getWhsId() + "#" + t.getLocId() + "#" + t.getOwner() + "#" +
         		t.getSkuId() + "#" + t.getFactory() + "#" + t.getVendorId() + "#" +
         		t.getLotno() + "#" + t.getInvAttr() + "#"), Collectors.toList()));
         	for (String goodsKey : goodsMap.keySet()) {
         		List<Goods> goodsList = goodsMap.get(goodsKey);
         		Goods invGoods = goodsList.get(0);
         		List<String> snList = goodsList.stream().map(Goods::getGoodsSn).distinct().collect(Collectors.toList());
         		BigDecimal qty = asnDtlGoodsList.stream().filter(t -> snList.contains(t.getGoodsSn())).map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
    			
    			// 扣减库存【原来QA状态库存】
    			UpdateInventoryInputDto oldInv = new UpdateInventoryInputDto();
    			oldInv.setWhsId(invGoods.getWhsId());			// 仓库
    			oldInv.setOwner(invGoods.getOwner());			// 货主
    			oldInv.setSkuId(invGoods.getSkuId());			// 物料
    			oldInv.setFactory(invGoods.getFactory());		// 组织
    			oldInv.setLotNo(invGoods.getLotno());			// 批次号
    			oldInv.setVendorId(invGoods.getVendorId());		// 供应商
    			oldInv.setInvAttr(invGoods.getInvAttr());		// 库存性质
    			oldInv.setQaStatus(oldQaStatus);				// 品质状态【旧】
    			oldInv.setUnit(invGoods.getUnit());				// 单位
    			oldInv.setLocId(invGoods.getLocId());       	// 库位
    			oldInv.setQty(qty.negate());					// 数量【-】
    			oldInv.setOperator(userName);
    			
    			// 库存日志【原来QA状态库存】
    	        InvTrans oldInvLog = new InvTrans();
    	        oldInvLog.setOpCode(OpCodeEnum.INSPECTIONRESULT.getDescription());
    	        oldInvLog.setDocType(asnHeader.getAsnType());
    	        oldInvLog.setDocNo(asnDtl.getAsnNo());
    	        oldInvLog.setDocLineNo(asnDtl.getAsnLineNo());
    	        oldInvLog.setTrsnNo(trsnDtl1.getNoteNo());
    	        oldInvLog.setTrsnLineNo(trsnDtl1.getNoteLineNo());
    	        oldInvLog.setStatus(InvTransStatusEnum.FINISHED.getCode());
    	        oldInvLog.setTransTime(date);
    	        oldInvLog.setOperator(userName);
    	        oldInvLog.setTransQty(oldInv.getQty());
    	        oldInvLog.setCreateTime(date);
    	        oldInvLog.setCreateUser(userName);
    	        
    	        // 扣减库存
    	        inventoryService.inventoryOut(oldInv, oldInvLog);
    	        
    	        //------------------------------------------//
    	        
    	        // 增加库存【判检后新的QA状态库存】
    	        UpdateInventoryInputDto newInv = new UpdateInventoryInputDto();
    	        newInv.setWhsId(invGoods.getWhsId());			// 仓库
    			newInv.setOwner(invGoods.getOwner());			// 货主
    			newInv.setSkuId(invGoods.getSkuId());			// 物料
    			newInv.setFactory(invGoods.getFactory());		// 组织
    			newInv.setLotNo(invGoods.getLotno());			// 批次号
    			newInv.setVendorId(invGoods.getVendorId());		// 供应商
    			newInv.setInvAttr(invGoods.getInvAttr());		// 库存性质
    			newInv.setQaStatus(newQaStatus);				// 品质状态【新】
    			newInv.setUnit(invGoods.getUnit());				// 单位
    			newInv.setLocId(invGoods.getLocId());       	// 库位
    			newInv.setQty(qty);								// 数量【+】
    			newInv.setOperator(userName);
    	        
    	        // 库存日志【判检后新的QA状态库存】
    	        InvTrans newInvLog = new InvTrans();
    	        newInvLog.setOpCode(OpCodeEnum.INSPECTIONRESULT.getDescription());
    	        newInvLog.setDocType(asnHeader.getAsnType());
    	        newInvLog.setDocNo(asnDtl.getAsnNo());
    	        newInvLog.setDocLineNo(asnDtl.getAsnLineNo());
    	        newInvLog.setTrsnNo(trsnDtl2.getNoteNo());
    	        newInvLog.setTrsnLineNo(trsnDtl2.getNoteLineNo());
    	        newInvLog.setStatus(InvTransStatusEnum.FINISHED.getCode());
    	        newInvLog.setTransTime(date);
    	        newInvLog.setOperator(userName);
    	        newInvLog.setTransQty(newInv.getQty());
    	        newInvLog.setCreateTime(date);
    	        newInvLog.setCreateUser(userName);
    	        
    	        // 增加库存
    	        inventoryService.inventoryIn(newInv, newInvLog);
    	        
    	        // 遍历条码
    	        for (Goods goods : goodsList) {
    	        	// 新增库存凭证--明细货品清单
    	        	BigDecimal goodsQty = asnDtlGoodsList.stream().filter(t -> goods.getGoodsSn().equals(t.getGoodsSn())).findFirst().map(t -> t.getQty()).get();
    	        	insertTrsnDtlGoods(trsnDtl1.getTrsnDtlId(), oldQaStatus, goods.getGoodsId(), goods.getGoodsSn(), goodsQty, userName, date);
    	        	insertTrsnDtlGoods(trsnDtl2.getTrsnDtlId(), newQaStatus, goods.getGoodsId(), goods.getGoodsSn(), goodsQty, userName, date);
    	        	
    	        	if(!goodsSnSet.contains(goods.getGoodsSn())) {
    	        		goodsSnSet.add(goods.getGoodsSn());
    	        		
    	        		// 更新货品清单的QA状态
    	        		String oldGoodsJsonStr = JSON.toJSONString(goods);	//原先的json
    	        		goods.setQaStatus(newQaStatus);
    	        		goods.setModifyTime(date);
    	        		goods.setModifyUser(userName);
    	        		goodsService.updateById(goods);
    	        		String newGoodsJsonStr = JSON.toJSONString(goods);	//更新后的json
    	        		
    	        		// 新增货品清单的日志
    	        		GoodsLog goodsLog = new GoodsLog();
    	        		goodsLog.setGoodsSn(goods.getGoodsSn());
    	        		goodsLog.setOpCode("判检" + goods.getGoodsSn());
    	        		goodsLog.setReason("变更品质状态");
    	        		goodsLog.setOperator("原材料-产品判检");
    	        		goodsLog.setUpdateContent("未更新的：" + oldGoodsJsonStr + ",更新后的：" + newGoodsJsonStr);
    	        		goodsLog.setCreateUser(userName);
    	        		goodsLog.setCreateTime(date);
    	        		goodsService.insertGoodsLog(goodsLog);
    	        	}
				}
         	}
         	
         	// 更新送货单明细
         	asnDtl.setQaStatus(newQaStatus);
         	asnDtl.setModifyUser(userName);
         	asnDtl.setModifyTime(date);
         	asnDtlMapper.updateById(asnDtl);
         	
         	// 更新送货单明细--货品清单
         	AsnDtlGoods asnDtlGoods = new AsnDtlGoods();
         	asnDtlGoods.setQaStatus(newQaStatus);
         	asnDtlGoods.setModifyUser(userName);
         	asnDtlGoods.setModifyTime(date);
         	asnDtlGoodsMapper.update(asnDtlGoods, asnDtlGoodsQueryWrapper);


         	// 更新检验单状态
         	/*qmsIqc.setInspectionStatus(QmsOqcStatusEnum.ALREADLY_CHECKED.getCode());	// 已报检【202】
         	qmsIqc.setModifyUser(userName);
         	qmsIqc.setModifyTime(date);
         	qmsIqcMapper.updateById(qmsIqc);*/
         	//回调SAP判检入库接口
            try {
                checkInStoreService.backToSap("1", newQaStatus+"", asnDtl, userName, asnHeader.getAsnNo(),remark,oqcNo);
            }catch (Exception e){
				Shift.fatal("调用SAP接口失败！！!");
            }
		}
        // 循环处理送货单明细---------------------------end---------------------//
    }
    
    private TrsnDtl insertTrsnHeaderAndTrsnDtl(Integer qaStatus, BigDecimal qty, AsnDtl asnDtl, AsnHeader asnHeader, 
    		int invUpdateFlag, String userName, Date date) throws Exception {
    	// 生成凭证号
        String noteNo = basicSimpleCodeRuleApi.GenerateCode(NOTE_NO);
        // 凭证表头
        TrsnHeader trsnHeader = new TrsnHeader();
        trsnHeader.setNoteNo(noteNo);
        trsnHeader.setNoteType(TrsnNoteTypeEnum.DRAW.getCode());	// 翻牌
        trsnHeader.setFmDoc(asnDtl.getAsnNo());
        trsnHeader.setWhsId(asnDtl.getWhsId());
        trsnHeader.setOwner(asnHeader.getOwner());
        trsnHeader.setFactory(asnHeader.getFactory());
        trsnHeader.setVendorId(asnHeader.getVendorId());
        trsnHeader.setFmDoc(SeparatorString.RIGHT_SLASH);
        trsnHeader.setDocRef1(SeparatorString.RIGHT_SLASH);
        trsnHeader.setDocRef2(SeparatorString.RIGHT_SLASH);
        trsnHeader.setDocRef3(SeparatorString.RIGHT_SLASH);
        trsnHeader.setDocRef4(SeparatorString.RIGHT_SLASH);
        trsnHeader.setDocRef5(SeparatorString.RIGHT_SLASH);
        trsnHeader.setComments(SeparatorString.RIGHT_SLASH);
        trsnHeader.setStatus(TrsnHeaderStatusEnum.CMP.code);
        trsnHeader.setCreateUser(userName);
        trsnHeader.setCreateTime(date);
        trsnHeaderMapper.insert(trsnHeader);
        
        // 凭证明细
        TrsnDtl trsnDtl = new TrsnDtl();
        trsnDtl.setNoteNo(noteNo);
        trsnDtl.setTrsnHeaderId(trsnHeader.getTrsnHeaderId());
        trsnDtl.setFmDoc(asnDtl.getAsnNo());
        trsnDtl.setFmDocLine(asnDtl.getAsnLineNo());
        trsnDtl.setQaStatus(qaStatus);
        trsnDtl.setSkuId(asnDtl.getSkuId());
        trsnDtl.setQty(qty);
        trsnDtl.setUnit(asnDtl.getUnit());
        trsnDtl.setInvUpdateFlag(invUpdateFlag);
        trsnDtl.setNoteLineNo("1");
        trsnDtl.setInvType("X");
        trsnDtl.setStatus(TrsnDtlStatusEnum.CMP.code);
        trsnDtl.setComments(SeparatorString.RIGHT_SLASH);
        trsnDtl.setCreateUser(userName);
        trsnDtl.setCreateTime(date);
        if (asnDtl.getLotno() != null) {
        	Lotno lotno = lotnoService.selectByLotno(asnDtl.getLotno());
        	if (lotno != null) {
        		trsnDtl.setLotAttr1(lotno.getLotAttr1());
        		trsnDtl.setLotAttr2(lotno.getLotAttr2());
        		trsnDtl.setLotAttr3(lotno.getLotAttr3());
        		trsnDtl.setLotAttr4(lotno.getLotAttr4());
        		trsnDtl.setLotAttr5(lotno.getLotAttr5());
        		trsnDtl.setLotAttr6(lotno.getLotAttr6());
        		trsnDtl.setLotAttr7(lotno.getLotAttr7());
        		trsnDtl.setLotAttr8(lotno.getLotAttr8());
        		trsnDtl.setLotAttr9(lotno.getLotAttr9());
        		trsnDtl.setLotAttr10(lotno.getLotAttr10());
        		trsnDtl.setLotAttr11(lotno.getLotAttr11());
        		trsnDtl.setLotAttr12(lotno.getLotAttr12());
            }
        }
        trsnDtlMapper.insert(trsnDtl);
        return trsnDtl;
    }
    
    private void insertTrsnDtlGoods(Integer trsnDtlId , Integer qaStatus, Integer goodsId, String goodsSn, 
    		BigDecimal qty, String userName, Date date) throws Exception {
    	// 凭证明细-goods
        TrsnDtlGoods trsnDtlGoods = new TrsnDtlGoods();
        trsnDtlGoods.setTrsnDtlId(trsnDtlId);
        trsnDtlGoods.setQaStatus(qaStatus);
        trsnDtlGoods.setGoodsId(goodsId);
        trsnDtlGoods.setGoodsSn(goodsSn);
        trsnDtlGoods.setQty(qty);
        trsnDtlGoods.setStatus(TrsnDtlGoodsStatusEnum.RECEIVED.getCode());
        trsnDtlGoods.setCreateUser(userName);
        trsnDtlGoods.setCreateTime(date);
        trsnDtlGoodsMapper.insert(trsnDtlGoods);
    }
}
